﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Threading;

namespace TestHarness
{
    class Program
    {
        static void Main(string[] args)
        {

            //Prompt("Launch app...");

            //string filename = "..\\..\\..\\Test\\bin\\debug\\Test.exe";
            //LaunchApp(filename);

            //Prompt("Find Form1 window");
            //IntPtr hwn = FindMainWindow("Form1");

            //Prompt("Find Click control..");
            //IntPtr hwnChild = FindControl(hwn, "XXXX");

            //Prompt("textbox ..");
            //SendMessageToTextbox(hwnChild, "hhh");

            //Prompt("get notepad");
            //IntPtr hwn = FindMainWindow("testcase.txt - notepad");

            //Prompt("get hmenu");
            //IntPtr hMenu = GetMenu(hwn);
            //Console.WriteLine("hmenu:" + hMenu);

            // uint WM_COMMAND = 0x0111;
            //Prompt("get hHelp");
            //IntPtr idHelp = GetSubMenu(hMenu, 3);
            //Console.WriteLine("idhelp:" + idHelp);

            //Prompt("get about id");
            //int aboutid = GetMenuItemID(idHelp, 0);
            //Console.WriteLine("aboutid:" + aboutid);


            ////SendMessage2(hwn, WM_COMMAND, idHelp, IntPtr.Zero);

            ////IntPtr hHelp = GetSubMenu(hMenu, 4);
            ////int about = GetMenuItemID(hHelp, 1);

            //Thread.Sleep(1000);
            //SendMessage2(hwn, WM_COMMAND, aboutid, IntPtr.Zero);


            //Prompt("send mes..");
            //IntPtr hwnchild = FindWindowByIndex(hwn, 1);
            //if(hwnchild!= IntPtr.Zero)
            //    SendMessageToTextbox(hwnchild, "yes");



            ManuplateNotepad();

            Console.ReadLine();
        }

        private static void ClickMenuItem(IntPtr hwnd, int menuID)
        {
            uint WM_COMMAND = 0x0111;
            
            PostMessage2 (hwnd, WM_COMMAND, menuID, IntPtr.Zero);
        }

        private static string GetNotepadPath()
        {
            string systemDrive = Environment.GetEnvironmentVariable("SystemDrive");
            return systemDrive + "\\windows\\system32\\notepad.exe";

        }

        private static void ManuplateNotepad()
        {
            string filename = GetNotepadPath();
            string title = "Untitled - Notepad";

            LaunchApp(filename);

            IntPtr hWnd = FindMainWindow(title);
            IntPtr hText = FindWindowByIndex(hWnd, 1);
            SendMessageToTextbox(hText, "I love you, darling...");

            IntPtr hMenu = GetMenu(hWnd);
            IntPtr hFile = GetSubMenu(hMenu, 0);
            int saveID = GetMenuItemID(hFile, 2);

            ClickMenuItem(hWnd, saveID);

            IntPtr hSaveas = FindMainWindow("Save As");
            //Console.WriteLine("Save as :"+To16String(hSaveas));

            Thread.Sleep(2000);

            //GetTree(hSaveas);
            IntPtr hpane = FindWindowByIndex(hSaveas, 1,"DUIViewWndClassName");
            //Console.WriteLine("Hpane:" + To16String(hpane));
            IntPtr hpane2 = FindWindowByIndex(hpane, 1, "DirectUIHWND");
            //Console.WriteLine("hpane2:" + To16String(hpane2));
            IntPtr hpane3 = FindWindowByIndex(hpane2, 1, "FloatNotifySink");
            //Console.WriteLine("hpane3:" + To16String(hpane3));
            IntPtr hpane4 = FindWindowByIndex(hpane3, 1, "ComboBox");
            //Console.WriteLine("hpane4:" + To16String(hpane4));

            IntPtr hFileName = FindWindowByIndex(hpane4, 1);
            //Console.WriteLine("hFilename:" + hFileName);

            SendMessageToTextbox(hFileName, DateTime.Now.Ticks + ".txt");

            IntPtr hButton = FindWindowByIndex(hSaveas, 5);
            ClickButtonByPost(hButton);

            
        }

        private static string To16String(IntPtr p)
        {
            return Convert.ToString(Convert.ToInt32(p.ToString()), 16);
        }


        private static void GetTree(IntPtr p,int index=0)
        {
            IntPtr result = IntPtr.Zero;
            //Console.WriteLine(To16String(p) + "start...");
            while ((result = FindWindowEx(p, result, null, null)) != IntPtr.Zero)
            {
                Console.WriteLine(GetString(' ',index*6)+ "--"+To16String(result));
                GetTree(result,index+1);
            }
            //Console.WriteLine(To16String(p) + "end...");
        }

        private static string GetString(char c, int count)
        {
            string str = "";
            for (int i = 0; i < count; i++)
            {
                str += c;
            }
            return str;
        }

        private static IntPtr FindWindowByIndex(IntPtr parent, int index,string className=null)
        {
            if (index == 0)
                return parent;
            else
            {
                int ct = 0;
                IntPtr result = IntPtr.Zero;
                do
                {
                    result = FindWindowEx(parent, result, className, null);
                    //Console.WriteLine(ct+":"+To16String(result));
                    if (result != IntPtr.Zero)
                        ++ct;
                } while (ct < index && result != IntPtr.Zero);
                return result;
            }
        }

        private static void Test()
        {
            Prompt("Launch app...");

            string filename = "..\\..\\..\\AppTest\\bin\\debug\\AppTest.exe";
            LaunchApp(filename);

            Prompt("Find Form1 window");
            IntPtr hwn = FindMainWindow("Form1");

            Prompt("Find Click control..");
            IntPtr hwnChild = FindControl(hwn, "OK");

            Prompt("Click by post");
            ClickButtonByPost(hwnChild);

            Prompt("Click by send");
            ClickButtonBySend(hwnChild);

            Prompt("Find OK control...");
            hwnChild = FindControl(hwn, "OK");

            Prompt("Send string...");
            SendMessageToTextbox(hwnChild, "Hello world");
        }

        private static void ClickButtonByPost(IntPtr hwn)
        {
            uint WM_LBUTTONDOWN = 0X0201;
            uint WM_LBUTTONUP = 0X0202;
            PostMessage1(hwn,WM_LBUTTONDOWN,0,0);
            PostMessage1(hwn,WM_LBUTTONUP,0,0);

        }

        private static void ClickButtonBySend(IntPtr hwn)
        {
            uint WM_LBUTTONDOWN = 0X0201;
            uint WM_LBUTTONUP = 0X0202;
            SendMessage1(hwn,WM_LBUTTONDOWN,0,0);
            SendMessage1(hwn,WM_LBUTTONUP,0,0);
        }

        private static void SendMessageToTextbox(IntPtr hwn, string text)
        {
            uint WM_CHAR = 0x0102;
            foreach(char c in text)
            {
                SendMessage1(hwn, WM_CHAR, c, 0);
                Thread.Sleep(100);
            }
        }

        private static IntPtr FindControl(IntPtr parent,string title,string className = null)
        {
            IntPtr mwh = IntPtr.Zero;
            bool formFound = false;
            int attemps = 0;

            while (!formFound && attemps < 25)
            {
                if (mwh == IntPtr.Zero)
                {
                    //Console.WriteLine("Control not yet found");
                    Thread.Sleep(100);
                    attemps++;
                    mwh = FindWindowEx(parent,IntPtr.Zero,className, title);
                }
                else
                {
                    //Console.WriteLine("Control has been found");
                    formFound = true;
                }
            }

            if (mwh == IntPtr.Zero)
            {
               // Console.WriteLine("Could not find Control");
            }
            else
            {
                //Console.WriteLine("Done" + mwh);
            }

            return mwh;

        }

        private static IntPtr FindMainWindow(string title)
        {
            IntPtr mwh = IntPtr.Zero;
            bool formFound = false;
            int attemps = 0;

            while (!formFound && attemps < 25)
            {
                if (mwh == IntPtr.Zero)
                {
                    //Console.WriteLine("Form not yet found");
                    Thread.Sleep(100);
                    attemps++;
                    mwh = FindWindow(null, title);
                }
                else
                {
                    //Console.WriteLine("Form has been found");
                    formFound = true;
                }
            }

            if (mwh == IntPtr.Zero)
            {
                //Console.WriteLine("Could not find main window");
            }
            else
            {
                //Console.WriteLine("Done" + mwh);
            }

            return mwh;
        }

        private static void Prompt(string display)
        {
            Console.WriteLine(display);
            Console.ReadLine();
        }

        private static void LaunchApp(string filename)
        {
            Process p = Process.Start(filename);

            if (p == null)
            {
                Console.WriteLine("Warning: process may already exist...");
            }

            //Console.WriteLine("Done");
        }


        [DllImport("user32.dll", EntryPoint = "FindWindow", CharSet = CharSet.Auto)]
        static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

        [DllImport("user32.dll", EntryPoint = "FindWindowEx", CharSet = CharSet.Auto)]
        static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);

        [DllImport("user32.dll",EntryPoint="PostMessage",CharSet=CharSet.Auto)]
        static extern bool PostMessage1(IntPtr hWnd, uint Msg, int wParam, int lParam);

        [DllImport("user32.dll", EntryPoint = "PostMessage", CharSet = CharSet.Auto)]
        static extern bool PostMessage2(IntPtr hWnd, uint Msg, int wParam, IntPtr lParam);

        [DllImport("user32.dll",EntryPoint="SendMessage",CharSet=CharSet.Auto)]
        static extern void SendMessage1(IntPtr hWnd, uint Msg, int wParam, int lParam);

        [DllImport("user32.dll")]
        static extern IntPtr GetMenu(IntPtr hWnd);

        [DllImport("user32.dll")]
        static extern IntPtr GetSubMenu(IntPtr hMenu, int nPos);

        [DllImport("user32.dll")]
        static extern int GetMenuItemID(IntPtr hMenu, int nPos);

        [DllImport("user32.dll", EntryPoint = "SendMessage", CharSet = CharSet.Auto)]
        static extern void SendMessage2(IntPtr hWnd, uint msg, int wParam, IntPtr lParam);
    }
}
